import os, os.path, glob, fnmatch, subprocess, sys
import argparse, filecmp, shutil
from datetime import datetime
from datetime import date

myVersion = "my version -xx"

# 检查文件的函数
def check_file(cf):
    if not os.path.isfile(cf):
        print("")
        print("FAIL: cannot find file ", cf)
        sys.exit("Aborted!")

# 判断是否是一个路径
def check_dir(cdir):
    if not os.path.exists(cdir):
        print("")
        print("FAIL: cannot find folder ", cdir)
        sys.exit("Aborted!")

#returns true if myname is contained in components to build
def build_me(components, myname):
    if "all" in components or myname in components:
        return True
    return False

#main entry  
if __name__ == '__main__': # 因此通过判断__name__的值，就可以区分py文件是直接被运行，还是被引入其他程序中 https://blog.csdn.net/wosind/article/details/90728198
    print("\nStarting xxx project build script ", myVersion)
    print(str(datetime.now())) # 打印现在时间

    scriptDir = os.path.dirname(os.path.realpath(__file__)) # 给出脚本的路径
    # projRoot = os.path.abspath(os.path.join(scriptDir, "..", "..", "..")) # 给出项目的路径，所以，脚本和项目的相对位置要设置好
    projRoot = os.path.abspath(os.path.join(scriptDir)) # 给出项目的路径，所以，脚本和项目的相对位置要设置好

    parser = argparse.ArgumentParser() # 解析命令
    #positional argument
    parser.add_argument('type', help='specify build type as Release or Debug')
    # #optional argument, solver solver has just 1 component
    parser.add_argument('projecName', help='specify the component to build')
    args = parser.parse_args()
    

    # 确定build的类型
    buildType="Release"
    if (args.type == "Release") or (args.type == "release") or (args.type == "RELEASE"):
        buildType = "Release"
    elif (args.type == "Debug") or (args.type == "debug")or (args.type == "DEBUG"):
        buildType = "Debug"
    else:
        print("Error: ")
        print("  Unrecognized build type " + args.type)
        sys.exit("Aborted!")
    
    try:
        
        # 这个方法的作用是执行一些命令行的命令，例如 sh xxx.sh , java -jar xxx.jar 等，(相当于执行shell命令？)
        # 会开启一个子进程去执行，并且等待子进程结束才继续执行其他的，使用起来非常方便，就是需要注意一些小细节
        subprocess.call(['cmake', '--version']) # subprocess 模块允许我们启动一个新进程，并连接到它们的输入/输出/错误管道，从而获取返回值。
        subprocess.call(['pwd'])
    except OSError:
        print("")
        print("Error: ")
        print("  Cannot find cmake")
        sys.exit("Aborted!")
    
    # 给出一些变量定义
    archSLTN = ""
    if os.name == "posix": # posix指的是linux/MAC
        if buildType == "Release":
            suffix = "_opt" # 后缀
        elif buildType == "Debug":
            suffix = "_dbg"
        elif buildType == "Coverage":
            suffix = "_dbg_cov"
        else:
            suffix = "_opt_cov"

        installSubDir = "linux64" + suffix # 给出install目录
        # install3p = "/devread/3p/linux64" # 给出依赖的位置
        buildInstallCMD = "make -j4 && make install" # 给出build的脚本命令
        buildTestCMD = "make tests" # 给出test的命令
        cmakeSLTN = "Unix Makefiles" # cmake使用的generator类型
        #compilers
        #compilerPath = "/usr/local"      #gcc 6.1
        compilerPath = "/usr"   #gcc 9.3 #给出gcc路径
        cCompiler = compilerPath + "/bin/gcc" # gcc位置
        cxxCompiler = compilerPath + "/bin/g++"# g++位置
        makeCmd = "/usr/local/bin/make" # make的位置
        if not os.path.isfile(makeCmd):# 如果make不再‘makeCmd’中的话
            makeCmd = "/usr/bin/make" # 认为其在此处
        check_file(makeCmd) # 判断其是不是file
    else:
        temp="other paltforms"

    cmakeSLTN = "\"" + cmakeSLTN + "\"" + archSLTN # 添加双引号
    installDir = os.path.join(projRoot, "install") # 添加install目录
    buildDir = os.path.join(projRoot, "build") # 添加builds目录
    sourceDir = os.path.join(projRoot) # 确定CMakeLists.txt文件目录
    ProjectSourceDir = os.path.join(sourceDir)
    if os.path.exists(buildDir):
            print()
            print("Warning: folder " + buildDir + " exists, deleting")
            print()
            shutil.rmtree(buildDir)
    os.makedirs(buildDir) # 创建builds的子目录

    

    # 检查目录，这些目录需要提前创建好
    check_dir(buildDir)
    check_dir(installDir)
    check_dir(sourceDir)

    print("")
    print("----------------------------------------------")  
    print("project root dir: ", projRoot)
    print("build type      : ", buildType)
    print("install dir     : ", installDir)
    
    #out_file.write(solverVersion)
    currDir = os.getcwd()

    actualInstall = os.path.join(installDir, installSubDir)
    configCMD = "cmake -D CMAKE_INSTALL_PREFIX:PATH=" + actualInstall
    if os.name == "posix":
        configCMD = configCMD + " -D CMAKE_BUILD_TYPE:STRING=" + buildType # build类型
        configCMD = configCMD + " -D CMAKE_C_COMPILER:PATH=" + cCompiler # c编译器位置 
        configCMD = configCMD + " -D CMAKE_CXX_COMPILER:PATH=" + cxxCompiler # c++编译器位置

    

    #-------------------------------------------------------------
    os.chdir(buildDir)
    if 1: # 可以作为判断生成哪个项目的入口
        # 判断是否存在mfe的目录
        if not (os.path.exists(ProjectSourceDir)):
            sys.exit("multife source folder does not exist!")

        # 判断install目录是否存在，若存在，则删除
        if os.path.exists(installDir):
            print()
            print("Warning: folder " + installDir + " exists, deleting")
            print()
            shutil.rmtree(installDir)
        os.makedirs(installDir) # 创建builds的子目录
        
        os.chdir(buildDir) # os.chdir() ！！！方法用于改变当前工作目录到指定的路径。

        # 结合cmake的-D指令给出build的额外指令
        mfeCMD = configCMD # 给出build的命令
        mfeCMD = mfeCMD + " -D USE_OPENMP:BOOL=TRUE"

        mfeCMD = mfeCMD + " -G " + cmakeSLTN
        mfeCMD = mfeCMD + " " + ProjectSourceDir # 给出source的目录

        print("------------")
        mfeCMD1="cmake ../ "
        subprocess.call(mfeCMD, shell=True) #启动shell脚本，执行mfeCMD指令，即‘cmake xxx‘指令
        print("------------")
        subprocess.call(buildInstallCMD, shell=True) # 即'make xxx'指令
    if 0: # 生成使用mylib的项目
        ii=3

    #print summary on screen
    print("")
    print("----------------------------------------------")
    print("Build completed!")
    print(str(datetime.now()))
